---
id: general
title: General
pagination_next: troubleshooting/faqs/eslint
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## How do I turn on a `@typescript-eslint` rule?

First make sure you've read the docs and understand ESLint configuration files:

- [Read our getting started guide](../../getting-started/Quickstart.mdx) to ensure your config is properly setup to start configuring our rules.
- [Checkout ESLint's documentation on configuring rules](https://eslint.org/docs/latest/use/configure/rules) to ensure you understand how to configure rules.

Our [rule docs](/rules) detail the options each rule supports under the "Options" heading.
We use TypeScript types to describe an `Options` tuple type for the rule which you can use to configure the rule.
In your config file the keys of the `rules` object are the names of the rules you wish to configure and the values follow the following form:

```ts
type Severity = 'off' | 'warn' | 'error';
type RuleConfig =
  | Severity
  | [Severity]
  | [
      Severity,
      // Options is the tuple type from the rule docs
      ...Options,
    ];
```

Some examples

<Tabs groupId="eslint-config">
<TabItem value="Flat Config">

```js title="eslint.config.mjs"
export default tseslint.config(
  // ... the rest of your config ...
  {
    rules: {
      // turns a rule on with no configuration (i.e. uses the default configuration)
      '@typescript-eslint/array-type': 'error',
      // turns on a rule with configuration
      '@typescript-eslint/no-explicit-any': ['warn', { ignoreRestArgs: true }],
    },
  },
);
```

</TabItem>
<TabItem value="Legacy Config">

```js title=".eslintrc.cjs"
module.exports = {
  // ... the rest of your config ...
  rules: {
    // turns a rule on with no configuration (i.e. uses the default configuration)
    '@typescript-eslint/array-type': 'error',
    // turns on a rule with configuration
    '@typescript-eslint/no-explicit-any': ['warn', { ignoreRestArgs: true }],
  },
};
```

</TabItem>
</Tabs>

## How can I ban `<specific language feature>`?

ESLint core contains the rule [`no-restricted-syntax`](https://eslint.org/docs/rules/no-restricted-syntax).
This generic rule allows you to specify a [selector](https://eslint.org/docs/developer-guide/selectors) for the code you want to ban, along with a custom error message.

You can use an AST visualization tool such as [typescript-eslint playground](/play#showAST=es) > _Options_ > _AST Explorer_ on its left sidebar by selecting _ESTree_ to help in figuring out the structure of the AST that you want to ban.

<details>
<summary>Banning confusing property uses</summary>

```jsonc
{
  "rules": {
    "no-restricted-syntax": [
      "error",

      // Ban accessing `constructor.name`:
      {
        "selector": "MemberExpression[object.property.name='constructor'][property.name='name']",
        "message": "'constructor.name' is not reliable after code minifier usage.",
      },

      // Ban get and set accessors:
      {
        "selector": "Property:matches([kind = \"get\"], [kind = \"set\"]), MethodDefinition:matches([kind = \"get\"], [kind = \"set\"])",
        "message": "Don't use get and set accessors.",
      },
    ],
  },
}
```

</details>

<details>
<summary>Banning specific uses of class properties</summary>

```jsonc
{
  "rules": {
    "no-restricted-syntax": [
      "error",

      // Ban `private` members:
      {
        "selector": ":matches(PropertyDefinition, MethodDefinition)[accessibility=\"private\"]",
        "message": "Use `#private` members instead.",
      },

      // Ban `#private` members:
      {
        "selector": ":matches(PropertyDefinition, MethodDefinition) > PrivateIdentifier.key",
        "message": "Use the `private` modifier instead.",
      },

      // Ban static `this`:
      {
        "selector": "MethodDefinition[static = true] ThisExpression",
        "message": "Prefer using the class's name directly.",
      },
    ],
  },
}
```

</details>

<details>
<summary>Banning specific uses of TypeScript enums</summary>

```jsonc
{
  "rules": {
    "no-restricted-syntax": [
      "error",

      // Ban all enums:
      {
        "selector": "TSEnumDeclaration",
        "message": "My reason for not using any enums at all.",
      },

      // Ban just `const` enums:
      {
        "selector": "TSEnumDeclaration[const=true]",
        "message": "My reason for not using const enums.",
      },

      // Ban just non-`const` enums:
      {
        "selector": "TSEnumDeclaration:not([const=true])",
        "message": "My reason for not using non-const enums.",
      },
    ],
  },
}
```

</details>

<details>
<summary>Banning specific uses of TypeScript tuples</summary>

```jsonc
{
  "rules": {
    "no-restricted-syntax": [
      "error",
      // enforce tuple members have labels
      {
        "selector": "TSTupleType > :not(TSNamedTupleMember)",
        "message": "All tuples should have labels.",
      },
    ],
  },
}
```

</details>

## How do I check to see what versions are installed?

If you have multiple versions of our tooling, it can cause various bugs for you.
This is because ESLint may load a different version each run depending on how you run it - leading to inconsistent lint results.

Installing our tooling in the root of your project does not mean that only one version is installed.
One or more of your dependencies may have its own dependency on our tooling, meaning `npm`/`yarn` will additionally install that version for use by that package.
For example, `react-scripts` (part of `create-react-app`) has a dependency on our tooling.

You can check what versions are installed in your project using the following commands:

```bash npm2yarn
npm list @typescript-eslint/eslint-plugin @typescript-eslint/parser
```

If you see more than one version installed, then you will have to either use [yarn resolutions](https://classic.yarnpkg.com/en/docs/selective-version-resolutions) to force a single version, or you will have to downgrade your root versions to match the dependency versions.

**The best course of action in this case is to wait until your dependency releases a new version with support for our latest versions.**

## Changes to one file are not reflected when linting other files in my IDE

> tl;dr: Restart your ESLint server to force an update.

ESLint currently does not have any way of telling parsers such as ours when an arbitrary file is changed on disk.
That means if you change file A that is imported by file B, it won't update lint caches for file B -- even if file B's text contents have changed.
Sometimes the only solution is to restart your ESLint editor extension altogether.

See [this issue comment](https://github.com/typescript-eslint/typescript-eslint/issues/5845#issuecomment-1283248238 'GitHub issue 5845, comment 1283248238: details on ESLint cross-file caching') for more information.

:::tip
[VS Code's ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) provides an `ESLint: Restart ESLint Server` action.
:::

### I get `no-unsafe-*` complaints for cross-file changes

See [Changes to one file are not reflected in linting other files in my IDE](#changes-to-one-file-are-not-reflected-when-linting-other-files-in-my-ide).
Rules such as [`no-unsafe-argument`](/rules/no-unsafe-argument), [`no-unsafe-assignment`](/rules/no-unsafe-assignment), and [`no-unsafe-call`](/rules/no-unsafe-call) are often impacted.

## How does typescript-eslint compare to native-speed linters?

"Native-speed" linters such as [Biome linter](https://biomejs.dev/linter), [Deno linter](https://docs.deno.com/runtime/manual/tools/linter), and [oxlint](https://oxc.rs/docs/guide/usage/linter.html) run in very fast languages such as Go or Rust, and so can generally run significantly faster than ESLint in non-type-aware-linting.
They can also be easier to configure because they don't need to support the full ecosystem and legacy trail of ESLint.

However, until they support [typed linting](../../getting-started/Typed_Linting.mdx), they aren't a full replacement for typescript-eslint.
If you plan on using them, we recommend "dual linting": using those linters for what they support, then adding in ESLint for typed linting in a parallel or second step.
Our `*-type-checked-only` [Shared Configs](../../users/Shared_Configurations.mdx) will enable only type-checked rules in your ESLint config.

For example, the following config enables only the recommended config's type-checked rules with [`recommendedTypeCheckedOnly`](../../users/Shared_Configurations.mdx#recommended-type-checked-only):

<Tabs groupId="eslint-config">
<TabItem value="Flat Config">

{/* prettier-ignore */}
```js title="eslint.config.mjs"
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  tseslint.configs.recommendedTypeCheckedOnly,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
);
```

</TabItem>
<TabItem value="Legacy Config">

```js title=".eslintrc.cjs"
module.exports = {
  extends: ['plugin:@typescript-eslint/recommended-type-checked-only'],
  parserOptions: {
    projectService: true,
    tsconfigRootDir: __dirname,
  },
  root: true,
};
```

</TabItem>
</Tabs>

For example, [oxlint's Integration > ESLint documentation](https://oxc.rs/docs/guide/usage/linter#eslint) describes how to turn off ESLint rules that are already supported by oxlint.

## "The '`<key>`' property is deprecated on '`<type>`' nodes. Use '`<key>`' instead." warnings

If you're seeing this warning, it's likely you're using an ESLint plugin (or other tooling) that hasn't been updated for typescript-eslint v6.
Make sure you're using the latest versions of each of your ESLint plugins (and other tooling).

If you're using many ESLint plugins, have updated each to their latest version, and you're not sure which one this complaint is coming from, try either or both of:

- Running with [`--trace-deprecation`](https://nodejs.org/api/cli.html#--trace-deprecation) (e.g. `npx cross-env NODE_OPTIONS=--trace-deprecation npm run lint`)
- Disabling half of them at a time to narrow down which plugin it is

Then make sure each of those plugins has a GitHub issue asking that they release a version supporting typescript-eslint v6.

:::tip
For developers updating ESLint rules in plugins that still need to support typescript-eslint v5: you may need to `||` fall back to the old property key if the new one doesn't exist:

```diff
- node.typeParameters
+ node.typeArguments || node.typeParameters
```

:::

For more context, see the [Some properties named typeParameters instead of typeArguments](https://github.com/typescript-eslint/typescript-eslint/issues/146) issue, and the implementing [fix: rename typeParameters to typeArguments where needed](https://github.com/typescript-eslint/typescript-eslint/pull/5384) pull request.

The [typescript-eslint v6 release post](/blog/announcing-typescript-eslint-v6-beta) has more information on typescript-eslint v6.

## My linting feels really slow

If you think you're having issues with performance, see our [Performance Troubleshooting documentation](../../troubleshooting/typed-linting/Performance.mdx).
